package com.knowswift.issues.mqtt.message;

import com.aliyuncs.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.knowswift.common.bean.issue.po.MonitorDevice;
import com.knowswift.common.bean.issue.po.MonitorRecord;
import com.knowswift.common.bean.project.po.MonitorSetting;
import com.knowswift.common.bean.project.vo.MonitorSettingVO;
import com.knowswift.common.common.GlobalProperty;
import com.knowswift.issues.mqtt.MqttMessageUtil;
import com.knowswift.issues.service.MonitorDeviceService;
import com.knowswift.issues.service.MonitorRecordService;
import com.knowswift.issues.service.MonitorSettingService;
import com.knowswift.issues.util.MonitorUtil;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;

@Component
public class DeviceStatusMessageHandler implements MqttMessageHandler {
    private final MonitorDeviceService monitorDeviceService;
    private final MonitorSettingService monitorSettingService;
    private final MonitorRecordService monitorRecordService;

    public DeviceStatusMessageHandler(MonitorDeviceService monitorDeviceService, MonitorSettingService monitorSettingService, MonitorRecordService monitorRecordService) {
        this.monitorDeviceService = monitorDeviceService;
        this.monitorSettingService = monitorSettingService;
        this.monitorRecordService = monitorRecordService;
    }

    @Override
    public void handleMessage(String topic, MqttMessage message) {
        String serialNumber = MqttMessageUtil.getSerialNumberFromTopic(topic);
        DeviceStatusMessageForReceive messageObject = MqttMessageUtil.readObject(message.getPayload(), DeviceStatusMessageForReceive.class);
        System.out.println(messageObject);
        MonitorDevice monitorDevice = monitorDeviceService.getOne(new LambdaQueryWrapper<MonitorDevice>()
                .eq(MonitorDevice::getSerialNumber, serialNumber), false);

        // 更新设备状态
        if (monitorDevice != null) {
            LocalDateTime now = LocalDateTime.now();
            monitorDevice.setLastMessageTime(now);
            Integer voltage = messageObject.getVoltage();
            monitorDevice.setVoltage(voltage);
            voltage = voltage == null ? 3300 : voltage;
            voltage = voltage >= 3600 ? 3600 : voltage;
            voltage = voltage <= 3300 ? 3300 : voltage;
            int battery = (voltage - 3300) * 100 / 300;
            monitorDevice.setBattery(battery);
            monitorDevice.setElectric(messageObject.getElectric());
            monitorDevice.setTemperature(messageObject.getTemperature());
            monitorDevice.setHumidity(messageObject.getHumidity());
            if (monitorDevice.getActivateTime() == null) {
                monitorDevice.setActivateTime(now);
            }

            if (monitorDevice.getAcceptPosition()) {
                // TODO 转坐标
                monitorDevice.setLatitude(convertDdToDegreesMinutes((Double.valueOf(messageObject.getLatitude()) / ((double) messageObject.getLatitudeRatio() / 100)) / 100));
                monitorDevice.setLongitude(convertDdToDegreesMinutes((Double.valueOf(messageObject.getLongitude()) / ((double) messageObject.getLongitudeRatio() / 100)) / 100));
            }

            List<MonitorSetting> settingList = monitorSettingService.list();
            MonitorSettingVO setting = MonitorUtil.getSetting(settingList);
            boolean isAlert = isAlert(messageObject, setting);
            monitorDevice.setDeviceStatus(isAlert ? GlobalProperty.DEVICE_STATUS_ALERT : GlobalProperty.DEVICE_STATUS_NORMAL);

            // 是否增加警报次数
            monitorDeviceService.updateById(monitorDevice);

            // 没有设置区间时 不做警报
            String remark = "";
            String alarmType="";
// 检查温度
            String tempRemark = checkRangeAlert(messageObject.getTemperature(), setting.getTemperatureMin(), setting.getTemperatureMax(), setting.getTemperatureEnable(), "温度");
            if (!tempRemark.isEmpty()) {
                remark += tempRemark + "; ";
                alarmType+="温度|";
            }
// 检查湿度
            String humidityRemark = checkRangeAlert(messageObject.getHumidity(), setting.getHumidityMin(), setting.getHumidityMax(), setting.getHumidityEnable(), "湿度");
            if (!humidityRemark.isEmpty()) {
                remark += humidityRemark + "; ";
                alarmType+="湿度|";
            }
// 检查电流
            String electricRemark = checkRangeAlert(messageObject.getElectric(), setting.getElectricityMin(), setting.getElectricityMax(), setting.getElectricityEnable(), "电流");
            if (!electricRemark.isEmpty()) {
                remark += electricRemark + "; ";
                alarmType+="电流|";
            }

            // 插入设备状态记录
            MonitorRecord monitorRecord = new MonitorRecord();
            monitorRecord.setDeviceId(monitorDevice.getDeviceId());
            monitorRecord.setAreaName(monitorDevice.getAreaName());
            monitorRecord.setModuleName(monitorDevice.getModuleName());
            monitorRecord.setProjectName(monitorDevice.getProjectName());
            monitorRecord.setMonitorObject("白蚁");
            monitorRecord.setLatitude(monitorDevice.getLatitude());
            monitorRecord.setLongitude(monitorDevice.getLongitude());
            monitorRecord.setBattery(battery);
            monitorDevice.setVoltage(voltage);
            monitorRecord.setElectric(monitorDevice.getElectric());
            monitorRecord.setHumidity(monitorDevice.getHumidity());
            monitorRecord.setRemark(remark);
            monitorRecord.setAlarmInfo("设备号"+serialNumber+"的设备，存在一条告警信息，请注意查看！");
            monitorRecord.setAlarmType(alarmType.isEmpty()?alarmType:alarmType.substring(0, alarmType.length() - 1));
            monitorRecord.setTemperature(monitorDevice.getTemperature());
            monitorRecord.setDeviceStatus(isAlert ? GlobalProperty.DEVICE_STATUS_ALERT : GlobalProperty.DEVICE_STATUS_NORMAL);

            monitorRecordService.save(monitorRecord);
        }
    }

    public static double convertDdToDegreesMinutes(double degrees) {
        // 提取整数部分，即度
        int deg = (int) degrees;
        // 提取小数部分，即分数转换为十进制
//        double min = (degrees - deg) * 60;
        double min = (degrees - deg)*100;
        return deg + min / 60;
    }

    private static boolean isAlert(DeviceStatusMessageForReceive messageObject, MonitorSettingVO setting) {
        boolean isAlert;
        boolean temperatureInRange = MonitorUtil.isInRange(messageObject.getTemperature(), setting.getTemperatureMin(), setting.getTemperatureMax());
        boolean humidityInRange = MonitorUtil.isInRange(messageObject.getHumidity(), setting.getHumidityMin(), setting.getHumidityMax());
        boolean electricInRange = MonitorUtil.isInRange(messageObject.getElectric(), setting.getElectricityMin(), setting.getElectricityMax());
        // 没有设置区间时 不做警报
        if (setting.getTemperatureMin() == null && setting.getTemperatureMax() == null
                && setting.getHumidityMin() == null && setting.getHumidityMax() == null
                && setting.getElectricityMin() == null && setting.getElectricityMax() == null) {
            isAlert = false;
        } else {
            isAlert = temperatureInRange || humidityInRange || electricInRange;
            //isAlert = (temperatureInRange&&setting.getTemperatureEnable()==1) || (humidityInRange&&setting.getHumiditEnable()==1) || (electricInRange&&setting.getElectricityEnable()==1);
        }
        return isAlert;
    }

    @Override
    public Byte supportMessageType() {
        return 0x03;
    }
    private String checkRangeAlert(Integer currentValue, Integer min, Integer max, int enableFlag, String valueName) {

        if (enableFlag != 1) {
            return "";
        }

        if (min == null || max == null) {
            return String.format("%s %.1f 异常（未设置有效范围）", valueName, currentValue);
        } else if (!MonitorUtil.isInRange(currentValue, min, max)) {
            return String.format("%s %d 异常，不在范围 %d-%d 内",valueName, currentValue, min, max);
        }

        return "";
    }

    public static void main(String[] args) {
//        System.out.println(convertDdToDegreesMinutes(119.0921566));

        DeviceStatusMessageForReceive deviceStatusMessageForReceive = new DeviceStatusMessageForReceive();
        deviceStatusMessageForReceive.setTemperature(211);
        deviceStatusMessageForReceive.setHumidity(100);
        deviceStatusMessageForReceive.setElectric(74);

        MonitorSettingVO monitorSettingVO = new MonitorSettingVO();
        monitorSettingVO.setTemperatureMin(20);
        monitorSettingVO.setTemperatureMax(40);
        monitorSettingVO.setHumidityMin(20);
        monitorSettingVO.setHumidityMax(60);
        monitorSettingVO.setElectricityMin(1);
        monitorSettingVO.setElectricityMax(80);

        System.out.println(isAlert(deviceStatusMessageForReceive, monitorSettingVO));
    }
}
